package com.example.demo.dao.daoImpl;

import com.example.demo.dao.jdbc.PlcJDBCMapper;
import com.example.demo.pojo.PlcData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * PlcMapperImpl  进行数据库与Mapper进行增删改查操作
 * zwj
 */
@Repository
public class PlcJDBCMapperImpl implements PlcJDBCMapper {
    private static  final Logger looger= LogManager.getLogger(PlcJDBCMapperImpl.class);
    //连接数据源
    private final DataSource dataSource;
    //引入数据源  构造函数注入
    public PlcJDBCMapperImpl(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 插入数据
     * @param plcData  plcDB6表中的字段
     * @return  影响的行数
     * @throws SQLException  数据库异常
     * 使用原生的jdbc进行插入操作
     */
    @Override
    public int insertPlc(PlcData plcData) throws SQLException {
        //SQL插入语句
        // 定义PLC数据字段列表（集中管理，便于后续增删改）
        List<String> plcDataFields = Arrays.asList(
                // 设备状态字段（按原始顺序排列）
                "emergency_stop_status_value",          // 设备急停状态
                "remote_control_status_value",          // 设备远程状态
                "manual_mode_status_value",             // 设备手动状态
                "auto_mode_status_value",               // 设备自动状态
                "power_on_status_value",                // 设备上电状态
                "electromagnet_status_value",           // 电磁铁运行状态
                "system_running_status_value",          // 系统运行状态
                "remote_animation_status_value",        // 远程动画控制状态
                "system_fault_status_value",            // 系统故障状态
                "rotation_forward_status_value",        // 旋转正转运动状态
                "rotation_backward_status_value",       // 旋转反转运动状态
                "lifting_up_status_value",              // 起升上升运动状态
                "lifting_down_status_value",            // 起升下降运动状态
                "trolley_forward_status_value",         // 大车向前运动状态
                "trolley_backward_status_value",        // 大车向后运动状态
                "cart_left_status_value",               // 小车向左运动状态
                "cart_right_status_value",              // 小车向右运动状态
                "trolley_front_limit_value",            // 大车前限位状态
                "trolley_rear_limit_value",             // 大车后限位状态
                "cart_left_limit_value",                // 小车左限位状态
                "cart_right_limit_value",               // 小车右限位状态
                "lifting_up_limit_value",               // 起升上限位
                "audible_visual_alarm_value",           // 声光报警状态
                "grabbing_completed_value",             // 抓取完成
                "releasing_completed_value",            // 释放完成
                "trolley_freq_feedback_value",          // 大车运行频率反馈
                "cart_freq_feedback_value",             // 小车运行频率反馈
                "lifting_freq_feedback_value",          // 起升运行频率反馈
                "trolley_current_pos_value",            // 大车当前位置坐标
                "cart_current_pos_value",               // 小车当前位置坐标
                "lifting_current_pos_value",            // 起升当前位置坐标
                "anti_sway_start_status_value",         // 防摇启动状态
                "equipment_moving_value",               // 设备运动中
                "equipment_idle_value",                 // 设备空闲
                "rotation_left_limit_value",            // 旋转左限位
                "rotation_right_limit_value",           // 旋转右限位
                "rotation_freq_feedback_value",         // 旋转运行频率反馈
                "rotation_angle_value",                 // 旋转角度
                "trolley_motor1_temp_value",            // 大车电机 1 温度
                "trolley_motor2_temp_value",            // 大车电机 2 温度
                "cart_motor_temp_value",                // 小车电机温度
                "lifting_motor1_temp_value",            // 起升电机 1 温度
                "lifting_motor2_temp",                  // 起升电机 2 温度
                "emergency_stop_status_value_time" // 时间戳
        );


        // 动态生成字段拼接字符串（如："device_id, tag_name, ..."）
        String fieldStr = String.join(", ", plcDataFields);

        // 动态生成与字段数量匹配的占位符（如："?, ?, ..."）
        String placeholderStr = IntStream.range(0, plcDataFields.size())
                .mapToObj(i -> "?")
                .collect(Collectors.joining(", "));

        // 构建完整的INSERT SQL语句
        String insertSql = String.format(
                "INSERT INTO plc_data_opc (%s) VALUES (%s)",
                fieldStr,
                placeholderStr
        );
        try(Connection connection=dataSource.getConnection();
        PreparedStatement statement=connection.prepareStatement(insertSql)) {
            // 动态设置plcDataFields列表中的所有参数（从索引1开始）
            int paramIndex = 1; // 从1开始计数，与SQL占位符顺序对应
            Class<?> plcDataClass = plcData.getClass();

            for (String fieldName : plcDataFields) {
                try {
                    // 获取字段对象（支持私有字段）
                    Field field = plcDataClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    Object fieldValue = field.get(plcData);

                    // 根据字段类型设置参数
                    if (field.getType() == Boolean.class) {
                        // 处理Boolean类型，默认值为false（可根据需求调整）
                        Boolean value = (Boolean) fieldValue;
                        statement.setBoolean(paramIndex, value != null ? value : false);
                    } else if (field.getType() == int.class) {
                        // 处理基本类型int（不会为null）
                        statement.setInt(paramIndex, field.getInt(plcData));
                    } else if (field.getType() == Integer.class) {
                        // 处理包装类型Integer，默认值为0（可根据需求调整）
                        Integer value = (Integer) fieldValue;
                        statement.setInt(paramIndex, value != null ? value : 0);
                    } else {
                        // 其他类型直接使用setObject（如未来扩展String等类型）
                        statement.setObject(paramIndex, fieldValue);
                    }

                    paramIndex++; // 移动到下一个参数索引

                } catch (NoSuchFieldException e) {
                    throw new RuntimeException("字段名不匹配：" + fieldName + " 不存在于plcData对象中", e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("无法访问字段：" + fieldName, e);
                }
            }
            return statement.executeUpdate();
        }catch (SQLException e){
            throw new SQLException("插入 plc数据失败!",e);
        }
    }
}
